package com.x.component.connectivity;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.x.component.connectivity.MobileMappings.Config;
import com.x.component.connectivity.MobileStatusTracker.SubscriptionDefaults;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserHandle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;

public class ConnectivityComponent {

	private HandlerThread handlerThread;
	private Handler bgHandler;
	private Handler foregroundHandler;

	private static final String TAG = "ConnectivityComponent";

	private static final Object mLock = new Object();

	private static ConnectivityComponent mInstance = null;

	private Context mContext;
	private int mUserId;
	
	private boolean simDetected;
	private boolean mobileDataEnabled;
	private MobileState mobileState;
	private WifiState wifiState;
	private int subId = 1;//simcard id
	
//	private boole(boolean show, boolean simDetected)

	private ConnectivityComponent(int userId) {
		this.mUserId = userId;
	}

	public static ConnectivityComponent getInstance() {
		if (null == mInstance) {
			synchronized (mLock) {
				if (null == mInstance) {
					mInstance = new ConnectivityComponent(UserHandle.USER_SYSTEM);
				}
			}
		}
		return mInstance;
	}

	private CopyOnWriteArrayList<ConnectivityTool> mConnectivityToolList = new CopyOnWriteArrayList<ConnectivityTool>();

	public boolean setConnectivityTool(ConnectivityTool ConnectivityTool) {
		if (ConnectivityTool != null && !mConnectivityToolList.contains(ConnectivityTool)) {
			mConnectivityToolList.add(ConnectivityTool);
			return true;
		}

		return false;
	}

	/**
	 * 注销mirror wifi 监听回调
	 *
	 * @param ConnectivityTool
	 * @return
	 */
	public boolean removeConnectivityTool(ConnectivityTool ConnectivityTool) {
		if (ConnectivityTool != null && mConnectivityToolList.contains(ConnectivityTool)) {
			mConnectivityToolList.remove(ConnectivityTool);
			return true;
		}
		return false;
	}

	public void init(Context context) {
		this.mContext = context;
		ConnectivityManager connectivityManager = FrameworkServicesModule.provideConnectivityManagager(context);
		TelephonyManager telephonyManager = FrameworkServicesModule.provideTelephonyManager(context);
		WifiManager wifiManager = FrameworkServicesModule.provideWifiManager(context);
		SubscriptionManager subManager = FrameworkServicesModule.provideSubcriptionManager(context);
		NetworkScoreManager networkScoreManager = FrameworkServicesModule.provideNetworkScoreManager(context);

		Config config = MobileMappings.Config.readConfig(context);

		HandlerThread handlerThread = new HandlerThread("ConnectivityComponent");
		handlerThread.start();
		bgHandler = new Handler(handlerThread.getLooper());

		ExecutorService bgExecutor = Executors.newSingleThreadExecutor();

		foregroundHandler = new Handler(Looper.getMainLooper());

//		CallbackHandler callbackHandler = new CallbackHandler(handlerThread.getLooper());
		CallbackHandler callbackHandler = new CallbackHandler(Looper.getMainLooper());
		callbackHandler.setListening(new SignalCallback() {

			@Override
			public void setWifiIndicators(WifiIndicators wifiIndicators) {
				Log.d(TAG, "setWifiIndicators");
				WifiState wifiState = wifiIndicators.wifiState;
				if (wifiState != null) {
					Log.d(TAG, "setWifiIndicators wifiState " + wifiState);
					setWifiState(wifiState);
				}
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setWifiIndicators(wifiIndicators);
				}

			}

			@Override
			public void setSubs(List<SubscriptionInfo> subs) {
				Log.d(TAG, "setSubs");
				for(SubscriptionInfo info:subs) {
					Log.d(TAG, "setSubs id: "+info.getSubscriptionId());
					subId = info.getSubscriptionId();
				}
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setSubs(subs);
				}

			}

			@Override
			public void setNoSims(boolean show, boolean simDetected) {
				Log.d(TAG, "setNoSims");
				setSimDetected(simDetected);
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setNoSims(show, simDetected);
				}

			}

			@Override
			public void setMobileDataIndicators(MobileDataIndicators mobileDataIndicators) {
				Log.d(TAG, "setMobileDataIndicators");
				MobileState mobileState = mobileDataIndicators.mobileState;
				if (mobileState != null) {
					setMobileState(mobileState);
					Log.d(TAG, "setMobileDataIndicators mobileState " + mobileState);
				}
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setMobileDataIndicators(mobileDataIndicators);
				}

			}

			@Override
			public void setMobileDataEnabled(boolean enabled) {
				Log.d(TAG, "setMobileDataEnabled");
				setMobileDataEnabled(enabled);
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setMobileDataEnabled(enabled);
				}

			}

			@Override
			public void setIsAirplaneMode(IconState icon) {
				Log.d(TAG, "setIsAirplaneMode: "+icon.visible);
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setIsAirplaneMode(icon);
				}

			}

			@Override
			public void setEthernetIndicators(IconState icon) {
				Log.d(TAG, "setEthernetIndicators");
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setEthernetIndicators(icon);
				}

			}

			@Override
			public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
					boolean noNetworksAvailable) {
				Log.d(TAG, "setConnectivityStatus noDefaultNetwork: "+noDefaultNetwork+" noValidatedNetwork:  "+noValidatedNetwork
						+" noNetworksAvailable: "+noNetworksAvailable);
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setConnectivityStatus(noDefaultNetwork, noValidatedNetwork, noNetworksAvailable);
				}

			}

			@Override
			public void setCallIndicator(IconState statusIcon, int subId) {
				Log.d(TAG, "setCallIndicator: "+subId);
				for (ConnectivityTool tool : mConnectivityToolList) {
					tool.setCallIndicator(statusIcon, subId);
				}

			}
		}, true);

		DataUsageController dataUsageController = new DataUsageController(context);

		SubscriptionDefaults defaultsHandler = new SubscriptionDefaults();

		WifiStatusTrackerFactory trackerFactory = new WifiStatusTrackerFactory(context, wifiManager,
				networkScoreManager, connectivityManager, foregroundHandler);

		NetworkControllerImpl impl = new NetworkControllerImpl(context, connectivityManager, telephonyManager,
				wifiManager, subManager, config, handlerThread.getLooper(), bgExecutor, callbackHandler,
				dataUsageController, defaultsHandler, trackerFactory, foregroundHandler);
	}

	public boolean isSimDetected() {
		return simDetected;
	}

	private void setSimDetected(boolean simDetected) {
		this.simDetected = simDetected;
	}

	public boolean isMobileDataEnabled() {
		return mobileDataEnabled;
	}

	private void setMobileDataEnabled(boolean mobileDataEnabled) {
		this.mobileDataEnabled = mobileDataEnabled;
	}

	public MobileState getMobileState() {
		return mobileState;
	}

	private void setMobileState(MobileState mobileState) {
		this.mobileState = mobileState;
	}

	public WifiState getWifiState() {
		return wifiState;
	}

	private void setWifiState(WifiState wifiState) {
		this.wifiState = wifiState;
	}
	
    /**
     * Set whether to enable data for {@code subId}, also whether to disable data for other
     * subscription
     */
    public void setMobileDataEnabled(boolean enabled,boolean disableOtherSubscriptions) {
        final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class)
                .createForSubscriptionId(subId);
        final SubscriptionManager subscriptionManager = mContext.getSystemService(
                SubscriptionManager.class);
        telephonyManager.setDataEnabled(enabled);
//        telephonyManager.isDataEnabled();
        if (disableOtherSubscriptions) {
            final List<SubscriptionInfo> subInfoList =
                    subscriptionManager.getActiveSubscriptionInfoList();
            if (subInfoList != null) {
                for (SubscriptionInfo subInfo : subInfoList) {
                    // We never disable mobile data for opportunistic subscriptions.
                    if (subInfo.getSubscriptionId() != subId && !subInfo.isOpportunistic()) {
                    	mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(
                                subInfo.getSubscriptionId()).setDataEnabled(false);
                    }
                }
            }
        }
    }
}
